use tauri_plugin_cli::CliExt;

#[derive(serde::Deserialize, Debug)]
struct TimeRange {
    start: chrono::NaiveTime,
    end: chrono::NaiveTime,
}

fn prepare_settings() -> Result<config::Config, String> {
    match dirs::document_dir() {
        Some(dir) => match dir.to_str() {
            Some(document_dir) => match config::Config::builder()
                .add_source(config::File::new(
                    format!("{document_dir}\\auto-play-news.ini").as_str(),
                    config::FileFormat::Ini,
                ))
                .build()
            {
                Ok(settings) => Ok(settings),
                Err(error) => Err(format!("Failed to get settings: {:?}.", error)),
            },
            None => Err("Failed to get document_dir.".into()),
        },
        None => Err("Failed to get dir.".into()),
    }
}

#[tauri::command]
fn get_data(name: &str) -> String {
    let now = chrono::Local::now().time();
    match name {
        "dir" => format!(
            "{:?}",
            dirs::document_dir().unwrap_or("Failed to get dir.".into())
        ),
        "document_dir" => match dirs::document_dir() {
            Some(dir) => format!(
                "{:?}",
                dir.to_str().unwrap_or("Failed to get document_dir.".into())
            ),
            None => "Failed to get dir.".into(),
        },
        "settings" => match prepare_settings() {
            Ok(settings) => format!("{:?}", settings),
            Err(error) => error,
        },
        "morning" => match prepare_settings() {
            Ok(settings) => match settings.get::<TimeRange>("morning") {
                Ok(morning) => format!("{:?}", morning),
                Err(error) => format!("Failed to get morning: {:?}.", error),
            },
            Err(error) => error,
        },
        "evening" => match prepare_settings() {
            Ok(settings) => match settings.get::<TimeRange>("evening") {
                Ok(evening) => format!("{:?}", evening),
                Err(error) => format!("Failed to get evening: {:?}.", error),
            },
            Err(error) => error,
        },
        "now" => format!("{:?}", now),
        "morning.start_now" => match prepare_settings() {
            Ok(settings) => match settings.get::<TimeRange>("morning") {
                Ok(morning) => {
                    format!("{:?}", morning.start <= now)
                }
                Err(error) => format!("Failed to get morning: {:?}.", error),
            },
            Err(error) => error,
        },
        "now_morning.end" => match prepare_settings() {
            Ok(settings) => match settings.get::<TimeRange>("morning") {
                Ok(morning) => format!("{:?}", now <= morning.end),
                Err(error) => format!("Failed to get morning: {:?}.", error),
            },
            Err(error) => error,
        },
        "is_morning" => match prepare_settings() {
            Ok(settings) => match settings.get::<TimeRange>("morning") {
                Ok(morning) => {
                    format!("{:?}", morning.start <= now && now <= morning.end)
                }
                Err(error) => format!("Failed to get morning: {:?}.", error),
            },
            Err(error) => error,
        },
        "evening.start_now" => match prepare_settings() {
            Ok(settings) => match settings.get::<TimeRange>("evening") {
                Ok(evening) => {
                    format!("{:?}", evening.start <= now)
                }
                Err(error) => format!("Failed to get evening: {:?}.", error),
            },
            Err(error) => error,
        },
        "now_evening.end" => match prepare_settings() {
            Ok(settings) => match settings.get::<TimeRange>("evening") {
                Ok(evening) => format!("{:?}", now <= evening.end),
                Err(error) => format!("Failed to get evening: {:?}.", error),
            },
            Err(error) => error,
        },
        "is_evening" => match prepare_settings() {
            Ok(settings) => match settings.get::<TimeRange>("evening") {
                Ok(evening) => {
                    format!("{:?}", evening.start <= now && now <= evening.end)
                }
                Err(error) => format!("Failed to get evening: {:?}.", error),
            },
            Err(error) => error,
        },
        "url" => match prepare_settings() {
            Ok(settings) => match settings.get::<TimeRange>("morning") {
                Ok(morning) => match settings.get::<TimeRange>("evening") {
                    Ok(evening) => {
                        if morning.start <= now && now <= morning.end {
                            return "https://tv.cctv.com/lm/wjxw/index.shtml".into();
                        } else if evening.start <= now && now <= evening.end {
                            return "https://tv.cctv.com/lm/xwlb/index.shtml".into();
                        } else {
                            return "Exit.".into();
                        }
                    }
                    Err(error) => format!("Failed to get evening: {:?}.", error),
                },
                Err(error) => format!("Failed to get morning: {:?}.", error),
            },
            Err(error) => error,
        },
        _ => "".into(),
    }
}

#[tauri::command]
fn navigate(href: String, mut window: tauri::WebviewWindow) {
    let url = tauri::Url::parse(href.as_str()).unwrap();
    window.navigate(url).unwrap();
}

pub fn run() {
    tauri::Builder::default()
        .plugin(
            tauri_plugin_log::Builder::new()
                .timezone_strategy(tauri_plugin_log::TimezoneStrategy::UseLocal)
                .targets([
                    tauri_plugin_log::Target::new(tauri_plugin_log::TargetKind::Stdout),
                    tauri_plugin_log::Target::new(tauri_plugin_log::TargetKind::LogDir {
                        file_name: Some(chrono::Local::now().format("%Y%m%dT%H%M%S").to_string()),
                    }),
                ])
                .build(),
        )
        // .plugin(tauri_plugin_single_instance::init(|_, _, _| {}))
        .plugin(tauri_plugin_cli::init())
        // .plugin(tauri_plugin_shell::init())
        .setup(|app| {
            log::info!("Setup");
            match app.cli().matches() {
                Ok(tauri_plugin_cli::Matches {
                    subcommand: Some(subcommand),
                    ..
                }) => {
                    log::debug!("Recognized subcommand: {:?}", subcommand);
                    if subcommand.name == "test".to_string() {
                        log::info!("Start test program");
                        tauri::WebviewWindowBuilder::new(
                            app,
                            "main",
                            tauri::WebviewUrl::App("gui.html".into()),
                        )
                        .title("测试")
                        .build()?;
                    }
                }
                Ok(tauri_plugin_cli::Matches {
                    subcommand: None, ..
                }) => {
                    log::info!("Start main program");
                    let document_dir = dirs::document_dir().unwrap();
                    let document_str = document_dir.to_str().unwrap();
                    log::debug!("Try to get config from: {}", document_str);

                    let settings = config::Config::builder()
                        .add_source(config::File::new(
                            format!("{document_str}\\auto-play-news.ini").as_str(),
                            config::FileFormat::Ini,
                        ))
                        .build()
                        .unwrap();

                    let morning = settings.get::<TimeRange>("morning").unwrap();
                    let evening = settings.get::<TimeRange>("evening").unwrap();

                    log::debug!("Config of morning: {:?}", morning);
                    log::debug!("Config of evening: {:?}", evening);

                    let now = chrono::Local::now().time();

                    let url;
                    if morning.start <= now && now <= morning.end {
                        url = tauri::Url::parse("https://tv.cctv.com/lm/wjxw/index.shtml").unwrap()
                    } else if evening.start <= now && now <= evening.end {
                        url = tauri::Url::parse("https://tv.cctv.com/lm/xwlb/index.shtml").unwrap()
                    } else {
                        log::warn!("Non-specified time");
                        app.handle().exit(0);
                        std::process::exit(0);
                    }
                    log::debug!("Open url: {}", url);

                    tauri::WebviewWindowBuilder::new(app, "main", tauri::WebviewUrl::External(url))
                        .title("播放新闻")
                        .maximized(true)
                        .fullscreen(true)
                        .on_navigation(|url| url.domain() == Some("tv.cctv.com"))
                        .on_page_load(|window, payload| match payload.event() {
                            tauri::webview::PageLoadEvent::Finished => {
                                window.eval(include_str!("./navigate.js")).unwrap()
                            }
                            _ => {}
                        })
                        .build()?;
                }
                Err(error) => {
                    log::error!("{}", error);
                    log::warn!("Non-specified subcommand");
                    app.handle().exit(0);
                }
            }
            Ok(())
        })
        .invoke_handler(tauri::generate_handler![navigate, get_data])
        .build(tauri::generate_context!())
        .expect("error while running tauri application")
        .run(|_, event| match event {
            tauri::RunEvent::ExitRequested { .. } => {
                log::info!("Exit requested")
            }
            tauri::RunEvent::Exit => {
                log::info!("Exit")
            }
            _ => {}
        });
}
